#include "point.h"
#include <stdlib.h>
#include <glib-object.h>

typedef struct _PointPoint {
  GObject parent_instance;

  gchar *class;

  gint64 id;
  gint64 parentID;
  gint64 oldID;
  gint64 timestamp;

  gint64 ctlID;
  gint64 eventID;
  gint64 updateTime;

  gboolean enable;
  gboolean update;
  gboolean negation;

  gint pushStatus;

  gint status;
  gint type;
  gint level;
  gint bitNumber;

  gchar *describe;
  gchar *name;//push(tag)
  gchar *file1;
  gchar *file2;//push(derivative)

  gchar *typeName;
  gchar *valueStr;

  gfloat value;
  gfloat oldValue;

  gfloat multiple;
  gfloat limit;
  gfloat levelValue1;
  gfloat levelValue2;

  GObject *son;
  GObject *parent;
  GObject *next;
  gpointer *private;
} PointPoint;
enum {
  PROP_0,
  PROP_CLASS,
  PROP_ID, PROP_PARENT_ID, PROP_OLD_ID, PROP_TIMESTAMP,
  PROP_CTL_ID, PROP_EVENT_ID, PROP_UPDATE_TIME,
  PROP_ENABLE, PROP_UPDATE, PROP_NEGATION,
  //, PROP_WARN_STATUS
  PROP_PUSH_STATUS,
  PROP_STATUS, PROP_TYPE, PROP_BIT_NUMBER, PROP_LEVEL,
  PROP_DESCRIBE, PROP_INDEX, PROP_FILE1, PROP_FILE2,
  PROP_TYPE_NAME, PROP_VALUE_STR,
  PROP_VALUE, PROP_OLD_VALUE,
  PROP_MULTIPLE, PROP_LIMIT, PROP_LEVEL1_VALUE, PROP_LEVEL2_VALUE,
  PROP_SON, PROP_PARENT, PROP_NEXT, PROP_PRIVATE,
  N_PROPERTIES };

static GParamSpec *properties[N_PROPERTIES] = { NULL, };

G_DEFINE_TYPE(PointPoint, point_point, G_TYPE_OBJECT)
//int64
static void point_point_set_id(PointPoint *obj, gint64 value)
{
  if (obj->id != value)
    {
      obj->id = value;

      g_assert(properties[PROP_ID] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_ID]);
    }
}
static void point_point_set_parentID(PointPoint *obj, gint64    value)
{
  if (obj->parentID != value)
    {
      obj->parentID = value;

      g_assert(properties[PROP_PARENT_ID] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_PARENT_ID]);
    }
}
static void point_point_set_oldID(PointPoint *obj, gint64    value)
{
  if (obj->oldID != value)
    {
      obj->oldID = value;

      g_assert(properties[PROP_OLD_ID] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_OLD_ID]);
    }
}
static void point_point_set_timestamp(PointPoint *obj, gint64    value)
{
  if (obj->timestamp != value)
    {
      obj->timestamp = value;

      g_assert(properties[PROP_TIMESTAMP] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_TIMESTAMP]);
    }
}
static void point_point_set_updateTime(PointPoint *obj, gint64    value)
{
  if (obj->updateTime != value)
    {
      obj->updateTime = value;

      g_assert(properties[PROP_UPDATE_TIME] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_UPDATE_TIME]);
    }
}
static void point_point_set_eventID(PointPoint *obj, gint64    value)
{
  if (obj->eventID != value)
    {
      obj->eventID = value;

      g_assert(properties[PROP_EVENT_ID] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_EVENT_ID]);
    }
}
static void point_point_set_ctlID(PointPoint *obj, gint    value)
{
  if (obj->ctlID != value)
    {
      obj->ctlID = value;

      g_assert(properties[PROP_CTL_ID] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_CTL_ID]);
    }
}
//int
static void point_point_set_level(PointPoint *obj, gint    value)
{
  if (obj->level != value)
    {
      obj->level = value;

      g_assert(properties[PROP_LEVEL] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj),
          properties[PROP_LEVEL]);
    }
}
static void point_point_set_type(PointPoint *obj, gint    value)
{
  if (obj->type != value)
    {
      obj->type = value;

      g_assert(properties[PROP_TYPE] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_TYPE]);
    }
}
static void point_point_set_bitNumber(PointPoint *obj, gint    value)
{
  if (obj->bitNumber != value)
    {
      obj->bitNumber = value;

      g_assert(properties[PROP_BIT_NUMBER] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_BIT_NUMBER]);
    }
}
//char
static void point_point_set_typeName(PointPoint  *obj, const gchar *value)
{
  if (g_strcmp0(obj->typeName, value) != 0)
    {
      g_free(obj->typeName);
      obj->typeName = g_strdup(value);

      g_assert(properties[PROP_TYPE_NAME] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_TYPE_NAME]);
    }
}
static void point_point_set_class(PointPoint  *obj, const gchar *value)
{
  if (g_strcmp0(obj->class, value) != 0)
    {
      g_free(obj->class);
      obj->class = g_strdup(value);

      g_assert(properties[PROP_CLASS] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_CLASS]);
    }
}
static void point_point_set_describe(PointPoint  *obj, const gchar *value)
{
  if (g_strcmp0(obj->describe, value) != 0)
    {
      g_free(obj->describe);
      obj->describe = g_strdup(value);

      g_assert(properties[PROP_DESCRIBE] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_DESCRIBE]);
    }
}
static void point_point_set_file1(PointPoint  *obj, const gchar *value)
{
  if (g_strcmp0(obj->file1, value) != 0)
    {
      g_free(obj->file1);
      obj->file1 = g_strdup(value);

      g_assert(properties[PROP_FILE1] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_FILE1]);
    }
}
static void point_point_set_file2(PointPoint  *obj, const gchar *value)
{
  if (g_strcmp0(obj->file2, value) != 0)
    {
      g_free(obj->file2);
      obj->file2 = g_strdup(value);

      g_assert(properties[PROP_FILE2] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_FILE2]);
    }
}
static void point_point_set_oldValue(PointPoint *obj, gfloat value)
{
  if (obj->oldValue != value)
    {
      obj->oldValue = value;

      g_assert(properties[PROP_OLD_VALUE] != NULL);
      g_object_notify_by_pspec(
          G_OBJECT(obj), properties[PROP_OLD_VALUE]);
    }
}
static void point_point_set_value(PointPoint *obj, gfloat value)
{
  if (obj->value != value)
    {
      obj->value = value;

      g_assert(properties[PROP_VALUE] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_VALUE]);
    }
}
static void
point_point_set_levelValue1(PointPoint  *obj, gfloat value)
{
  if (obj->levelValue1 != value)
    {
      obj->levelValue1 = value;

      g_assert(properties[PROP_LEVEL1_VALUE] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_LEVEL1_VALUE]);
    }
}
static void
point_point_set_levelValue2(PointPoint  *obj, gfloat value)
{
  if (obj->levelValue2 != value)
    {
      obj->levelValue2 = value;

      g_assert(properties[PROP_LEVEL2_VALUE] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_LEVEL2_VALUE]);
    }
}
static void
point_point_set_name(PointPoint  *obj,
                     const gchar *value)
{
  if (g_strcmp0(obj->name, value) != 0)
    {
      g_free(obj->name);
      obj->name = g_strdup(value);

      g_assert(properties[PROP_INDEX] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_INDEX]);
    }
}
//float
static void point_point_set_multiple(PointPoint *obj, gfloat    value)
{
  if (obj->multiple != value) {
      obj->multiple = value;
      g_assert(properties[PROP_MULTIPLE] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_MULTIPLE]);
    }
}
static void
point_point_set_limit(PointPoint *obj,
                     gfloat    value)
{
  if (obj->limit != value)
    {
      obj->limit = value;

      g_assert(properties[PROP_LIMIT] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_LIMIT]);
    }
}
//gobject
static void point_point_set_next(PointPoint  *obj, gpointer next)
{
    obj->next = next;
}
static void point_point_set_son(PointPoint  *obj, gpointer son)
{
    obj->son = son;
}
static void point_point_set_parent(PointPoint  *obj, gpointer value)
{
    obj->parent = value;
}

static void point_point_finalize(GObject *gobject)
{
  PointPoint *self = (PointPoint *) gobject;

  if (self->next)
    g_object_unref(self->next);
  if (self->son)
    g_object_unref(self->son);
  if (self->name)
    g_free(self->name);

  G_OBJECT_CLASS(point_point_parent_class)->finalize(gobject);
}

static void
point_point_set_property(GObject *gobject,
                          guint prop_id,
                          const GValue *value,
                          GParamSpec *pspec)
{
  PointPoint *tobj = (PointPoint *) gobject;

  g_assert_cmpint(prop_id, !=, 0);
  g_assert_cmpint(prop_id, !=, N_PROPERTIES);
  g_assert(pspec == properties[prop_id]);

  switch (prop_id)
    {
      //int64
    case PROP_ID:
      point_point_set_id(tobj, g_value_get_int64(value));
      break;
    case PROP_PARENT_ID:
      point_point_set_parentID(tobj, g_value_get_int64(value));
      break;
    case PROP_OLD_ID:
      point_point_set_oldID(tobj, g_value_get_int64(value));
      break;
    case PROP_TIMESTAMP:
      point_point_set_timestamp(tobj, g_value_get_int64(value));
      break;

    case PROP_EVENT_ID:
      point_point_set_eventID(tobj, g_value_get_int64(value));
      break;
    case PROP_UPDATE_TIME:
      point_point_set_updateTime(tobj, g_value_get_int64(value));
      break;
    case PROP_CTL_ID:
      point_point_set_ctlID(tobj, g_value_get_int64(value));
      break;
      //boolean
    case PROP_ENABLE:
      tobj->enable = g_value_get_boolean(value);
      break;
    case PROP_UPDATE:
      tobj->update = g_value_get_boolean(value);
      break;
    case PROP_NEGATION:
      tobj->negation = g_value_get_boolean(value);
      break;
      //int
    case PROP_PUSH_STATUS:
      tobj->pushStatus = g_value_get_int(value);
      break;

    case PROP_STATUS:
      tobj->status = g_value_get_int(value);
      break;
    case PROP_TYPE:
      point_point_set_type(tobj, g_value_get_int(value));
      break;
    case PROP_BIT_NUMBER:
      point_point_set_bitNumber(tobj, g_value_get_int(value));
      break;
    case PROP_LEVEL:
      point_point_set_level(tobj, g_value_get_int(value));
      break;
      //char
    case PROP_CLASS:
      point_point_set_class(tobj, g_value_get_string(value));
      break;
    case PROP_TYPE_NAME:
      point_point_set_typeName(tobj, g_value_get_string(value));
      break;
    case PROP_VALUE_STR:
      if (tobj->valueStr)
        g_free(tobj->valueStr);
      tobj->valueStr = g_strdup(g_value_get_string(value));
      break;

    case PROP_DESCRIBE:
      point_point_set_describe(tobj, g_value_get_string(value));
      break;
    case PROP_INDEX:
      point_point_set_name(tobj, g_value_get_string(value));
      break;
    case PROP_FILE1:
      point_point_set_file1(tobj, g_value_get_string(value));
      break;
    case PROP_FILE2:
      point_point_set_file2(tobj, g_value_get_string(value));
      break;
      //object
    case PROP_NEXT:
      point_point_set_next(tobj, g_value_get_pointer(value));
      break;
    case PROP_SON:
      point_point_set_son(tobj, g_value_get_pointer(value));
      break;
    case PROP_PARENT:
      point_point_set_parent(tobj, g_value_get_pointer(value));
      break;
      //float
    case PROP_VALUE:
      point_point_set_value(tobj, g_value_get_float(value));
      break;
    case PROP_OLD_VALUE:
      point_point_set_oldValue(tobj, g_value_get_float(value));
      break;

    case PROP_MULTIPLE:
      point_point_set_multiple(tobj, g_value_get_float(value));
      break;
    case PROP_LIMIT:
      point_point_set_limit(tobj, g_value_get_float(value));
      break;
    case PROP_LEVEL1_VALUE:
      point_point_set_levelValue1(tobj, g_value_get_float(value));
      break;
    case PROP_LEVEL2_VALUE:
      point_point_set_levelValue2(tobj, g_value_get_float(value));
      break;

    case PROP_PRIVATE:
      tobj->private = g_value_get_pointer(value);
      break;
    default:
      g_assert_not_reached();
    }
}

static void
point_point_get_property(GObject *gobject,
                          guint prop_id,
                          GValue *value,
                          GParamSpec *pspec)
{
  PointPoint *tobj = (PointPoint *) gobject;

  g_assert_cmpint(prop_id, !=, 0);
  g_assert_cmpint(prop_id, !=, N_PROPERTIES);
  g_assert(pspec == properties[prop_id]);

  switch (prop_id)
    {
    case PROP_ID:
      g_value_set_int64(value, tobj->id);
      break;
    case PROP_PARENT_ID:
      g_value_set_int64(value, tobj->parentID);
      break;
    case PROP_OLD_ID:
      g_value_set_int64(value, tobj->oldID);
      break;
    case PROP_TIMESTAMP:
      g_value_set_int64(value, tobj->timestamp);
      break;

    case PROP_EVENT_ID:
      g_value_set_int64(value, tobj->eventID);
      break;
    case PROP_UPDATE_TIME:
      g_value_set_int64(value, tobj->updateTime);
      break;
    case PROP_CTL_ID:
      g_value_set_int64(value, tobj->ctlID);
      break;

    case PROP_PUSH_STATUS:
      g_value_set_int(value, tobj->pushStatus);
      break;

    case PROP_STATUS:
      g_value_set_int(value, tobj->status);
      break;
    case PROP_ENABLE:
      g_value_set_boolean(value, tobj->enable);
      break;
    case PROP_UPDATE:
      g_value_set_boolean(value, tobj->update);
      break;
    case PROP_NEGATION:
      g_value_set_boolean(value, tobj->negation);
      break;

    case PROP_BIT_NUMBER:
      g_value_set_int(value, tobj->bitNumber);
      break;
    case PROP_TYPE:
      g_value_set_int(value, tobj->type);
      break;
    case PROP_LEVEL:
      g_value_set_int(value, tobj->level);
      break;

    case PROP_CLASS:
      g_value_set_string(value, tobj->class);
      break;
    case PROP_TYPE_NAME:
      g_value_set_string(value, tobj->typeName);
      break;
    case PROP_VALUE_STR:
      g_value_set_string(value, tobj->valueStr);
      break;

    case PROP_DESCRIBE:
      g_value_set_string(value, tobj->describe);
      break;
    case PROP_FILE1:
      g_value_set_string(value, tobj->file1);
      break;
    case PROP_FILE2:
      g_value_set_string(value, tobj->file2);
      break;

    case PROP_VALUE:
      g_value_set_float(value, tobj->value);
      break;
    case PROP_OLD_VALUE:
      g_value_set_float(value, tobj->oldValue);
      break;
    case PROP_MULTIPLE:
      g_value_set_float(value, tobj->multiple);
      break;
    case PROP_LIMIT:
      g_value_set_float(value, tobj->limit);
      break;
    case PROP_LEVEL1_VALUE:
      g_value_set_float(value, tobj->levelValue1);
      break;
    case PROP_LEVEL2_VALUE:
      g_value_set_float(value, tobj->levelValue2);
      break;

    case PROP_INDEX:
      g_value_set_string(value, tobj->name);
      break;
      
    case PROP_NEXT:
      g_value_set_pointer(value, tobj->next);
      break;
    case PROP_SON:
      g_value_set_pointer(value, tobj->son);
      break;
    case PROP_PARENT:
      g_value_set_pointer(value, tobj->parent);
      break;
    case PROP_PRIVATE:
      g_value_set_pointer(value, tobj->private);
      break;
    default:
      g_assert_not_reached();
    }
}

static void
point_point_class_init(PointPointClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS(klass);

  properties[PROP_ID] = g_param_spec_int64("id", "id", "Id",
      -1, G_MAXINT64, 0, G_PARAM_READWRITE);
  properties[PROP_PARENT_ID] = g_param_spec_int64(
      "parentID", "parentID", "ParentId",
      -1, G_MAXINT64, 0, G_PARAM_READWRITE);
  properties[PROP_OLD_ID] = g_param_spec_int64("oldID", "oldID", "OldId",
      -1, G_MAXINT64, 0, G_PARAM_READWRITE);
  properties[PROP_TIMESTAMP] = g_param_spec_int64(
      "timestamp", "timestamp", "timestamp",
      -1, G_MAXINT64, 0, G_PARAM_READWRITE);

  properties[PROP_CTL_ID] = g_param_spec_int64("ctlID", "ctlID", "CtlId",
      -1, G_MAXINT64, 0, G_PARAM_READWRITE);
  properties[PROP_EVENT_ID] = g_param_spec_int64(
      "eventID", "eventID", "EventId",
      G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE);
  properties[PROP_UPDATE_TIME] = g_param_spec_int64(
      "updateTime", "updateTime", "updateTime",
      -1, G_MAXINT64, 0, G_PARAM_READWRITE);

  properties[PROP_LEVEL] = g_param_spec_int(
      "level", "Level", "level",
      -1, G_MAXINT, 0, G_PARAM_READWRITE);
  properties[PROP_PUSH_STATUS] = g_param_spec_int(
      "pushStatus", "PushStatus", "push status",
      G_MININT, G_MAXINT, 0, G_PARAM_READWRITE);
  properties[PROP_STATUS] = g_param_spec_int(
      "status", "Status", "Status",
      G_MININT, G_MAXINT, 0, G_PARAM_READWRITE);
  properties[PROP_TYPE] = g_param_spec_int(
      "type", "type", "type",
      -1, G_MAXINT, 0, G_PARAM_READWRITE);
  properties[PROP_BIT_NUMBER] = g_param_spec_int(
      "bitNumber", "bitNumber", "bitNumber",
      -1, G_MAXINT, 0, G_PARAM_READWRITE);

  properties[PROP_ENABLE] = g_param_spec_boolean(
      "enable", "Enable", "enable",
      FALSE, G_PARAM_READWRITE);
  properties[PROP_UPDATE] = g_param_spec_boolean(
      "update", "update", "Update",
      FALSE, G_PARAM_READWRITE);
  properties[PROP_NEGATION] = g_param_spec_boolean(
      "negation", "Negation", "Negation", FALSE, G_PARAM_READWRITE);

  properties[PROP_CLASS] = g_param_spec_string(
      "class", "class", "class",
      NULL, G_PARAM_READWRITE);
  properties[PROP_TYPE_NAME] = g_param_spec_string(
      "typeName", "TypeName", "TYPENAME",
      NULL, G_PARAM_READWRITE);
  properties[PROP_VALUE_STR] = g_param_spec_string(
      "valueStr", "ValueStr", "value str",
      NULL, G_PARAM_READWRITE);

  properties[PROP_DESCRIBE] = g_param_spec_string(
      "describe", "describe", "describe",
      NULL, G_PARAM_READWRITE);
  properties[PROP_INDEX] = g_param_spec_string(
      "name", "name", "name",
      NULL, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
  properties[PROP_FILE1] = g_param_spec_string("file1", "file1", "file1",
      NULL, G_PARAM_READWRITE);
  properties[PROP_FILE2] = g_param_spec_string("file2", "file2", "file2",
      NULL, G_PARAM_READWRITE);

  properties[PROP_OLD_VALUE] = g_param_spec_float(
      "oldValue", "OldValue", "OldValue",
      -G_MAXFLOAT, G_MAXFLOAT, 0,
      G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
  properties[PROP_VALUE] = g_param_spec_float("value", "value", "value",
      -G_MAXFLOAT, G_MAXFLOAT, 0,
      G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
  properties[PROP_MULTIPLE] = g_param_spec_float(
      "multiple", "multiple", "multiple",
      -G_MAXFLOAT, G_MAXFLOAT, 1.0, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
  properties[PROP_LIMIT] = g_param_spec_float(
      "limit", "limit", "limit",
      -G_MAXFLOAT, G_MAXFLOAT, 1.0, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
  properties[PROP_LEVEL1_VALUE] = g_param_spec_float(
      "levelValue1", "Level1Value", "levelValue1",
      -G_MAXFLOAT, G_MAXFLOAT, 0, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
  properties[PROP_LEVEL2_VALUE] = g_param_spec_float(
      "levelValue2", "Level2Value", "levelValue2",
      -G_MAXFLOAT, G_MAXFLOAT, 0, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);

  properties[PROP_SON] = g_param_spec_pointer("son", "son", "son",
      G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
  properties[PROP_NEXT] = g_param_spec_pointer("next", "next", "next",
      G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
  properties[PROP_PARENT] = g_param_spec_pointer(
      "parent", "parent", "parent",
      G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
  properties[PROP_PRIVATE] = g_param_spec_pointer(
      "private", "Private", "private",
      G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);

  gobject_class->set_property = point_point_set_property;
  gobject_class->get_property = point_point_get_property;
  gobject_class->finalize = point_point_finalize;

  g_object_class_install_properties(gobject_class, N_PROPERTIES, properties);
}
static void
point_point_init(PointPoint *self)
{
  self->multiple = 1.0;
}

//PointPoint *point_point_new(void)
GObject *point_point_new(void)
{
  return g_object_new(POINT_POINT_TYPE, NULL);
}
